using Abp.Authorization;
using Abp.Authorization.Roles;
using Abp.Authorization.Users;
using Abp.MultiTenancy;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using System.Linq;
using Yozeev.Authorization;
using Yozeev.Authorization.Roles;
using Yozeev.BusinessLogic.Authorization;
using Yozeev.EntityFrameworkCore;
using Yozeev.PhoneBooks.Books.Authorization;
using Yozeev.SystemConfig.Authorization;
using Yozeev.SystemConfig.BasicConfig.Authorization;
using Yozeev.SystemConfig.SystemRecord.Authorization;
using Yozeev.UserManagerment.Users;
using Yozeev.WechatManagement.WechatAppConfigs.Authorization;

namespace Yozeev.Seed.Tenants
{
    public class TenantRoleAndUserBuilder
    {
        private readonly YozeevDbContext _context;
        private readonly int _tenantId;

        public TenantRoleAndUserBuilder(YozeevDbContext context, int tenantId)
        {
            _context = context;
            _tenantId = tenantId;
        }

        public void Create()
        {
            CreateRolesAndUsers();

            //CreateMemberRoles();
        }

        private void CreateRolesAndUsers()
        {
            // Admin role

            var adminRole = _context.Roles.IgnoreQueryFilters()
                .FirstOrDefault(r => r.TenantId == _tenantId && r.Name == StaticRoleNames.Tenants.Admin);
            if (adminRole == null)
            {
                adminRole = _context.Roles
                    .Add(new Role(_tenantId, StaticRoleNames.Tenants.Admin, StaticRoleNames.Tenants.Admin)
                    {
                        IsStatic = true,
                        IsDefault = false
                    }).Entity;
                _context.SaveChanges();
            }

            // Grant all permissions to admin role

            var grantedPermissions = _context.Permissions.IgnoreQueryFilters()
                .OfType<RolePermissionSetting>()
                .Where(p => p.TenantId == _tenantId && p.RoleId == adminRole.Id)
                .Select(p => p.Name)
                .ToList();

            var permissions = PermissionFinder
                .GetAllPermissions(
                    new AppProAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new WechatAppConfigAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new BooksAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //system
                    new PayMethodAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new DateDictionaryAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new BranchAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new BranchUserAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new CheckRecordAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ClientVersionAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //Boat
                    new BoatAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new RouteAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ScheduleAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new WharfAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //Device
                    new DeviceAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new GateRecordAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new VerifiableSetAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //common
                    new CustomerAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ScenicSpotAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new SourceAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new CommonCustomerAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //Ticket
                    new AccountAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new AccountDetailAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ActivityAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ActivityDetailAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ActivityTempAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new ActivityTempDetailAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new PriceAuditAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketDetailAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketDetailHistoryAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketIntroduceAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketPriceAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketStationAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketStationEnableAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketUserEnableAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketScheduleEnableAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TicketRoleAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //Travel
                    new RechargeRecordAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TravelAgencyAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new TravelTicketDetailAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //Power
                    new MenuAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new PowerAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new PowerRoleAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    //Print
                    new PrintStyleAuthorizationProvider(AppConsts.MultiTenancyEnabled),
                    new PrintStyleChildAuthorizationProvider(AppConsts.MultiTenancyEnabled)
                )
                .Where(p => p.MultiTenancySides.HasFlag(MultiTenancySides.Tenant) &&
                            !grantedPermissions.Contains(p.Name))
                .ToList();

            if (permissions.Any())
            {
                _context.Permissions.AddRange(
                    permissions.Select(permission => new RolePermissionSetting
                    {
                        TenantId = _tenantId,
                        Name = permission.Name,
                        IsGranted = true,
                        RoleId = adminRole.Id
                    })
                );
                _context.SaveChanges();
            }

            // Admin user

            var adminUser = _context.Users.IgnoreQueryFilters()
                .FirstOrDefault(u => u.TenantId == _tenantId && u.UserName == AbpUserBase.AdminUserName);
            if (adminUser == null)
            {
                adminUser = User.CreateTenantAdminUser(_tenantId, "ltm@ddxc.org");
                adminUser.Password =
                    new PasswordHasher<User>(new OptionsWrapper<PasswordHasherOptions>(new PasswordHasherOptions()))
                        .HashPassword(adminUser, User.DefaultPassword);
                adminUser.IsEmailConfirmed = true;
                adminUser.IsActive = true;
                adminUser.NeedToChangeThePassword = false;
                _context.Users.Add(adminUser);
                _context.SaveChanges();

                // Assign Admin role to admin user
                _context.UserRoles.Add(new UserRole(_tenantId, adminUser.Id, adminRole.Id));
                _context.SaveChanges();
            }
        }

    }
}